<!-- eslint-disable vue/multi-word-component-names -->
<template>
  <div class="image-upload-container">
    <h2>图片上传测试</h2>

    <!-- 文件选择 -->
    <div class="upload-section">
      <input
        ref="fileInput"
        type="file"
        accept="image/*"
        @change="handleFileSelect"
        :disabled="uploading"
      />
      <button @click="triggerFileSelect" :disabled="uploading">选择图片</button>
    </div>

    <!-- 图片预览 -->
    <div v-if="previewUrl" class="preview-section">
      <h3>预览图片</h3>
      <img :src="previewUrl" alt="预览图片" class="preview-image" />
      <p>文件名: {{ selectedFile?.name }}</p>
      <p>文件大小: {{ formatFileSize(selectedFile?.size || 0) }}</p>
    </div>

    <!-- 上传按钮和进度条 -->
    <div v-if="selectedFile" class="upload-controls">
      <div class="button-group">
        <button @click="handleUpload" :disabled="uploading">
          {{ uploading ? '上传中...' : '开始上传' }}
        </button>
        <button @click="handleReset" :disabled="uploading" class="reset-btn">重置</button>
      </div>

      <!-- 上传进度条 -->
      <div v-if="uploading" class="progress-section">
        <div class="progress-bar">
          <div class="progress-fill" :style="{ width: progress.percent + '%' }"></div>
        </div>
        <p>
          上传进度: {{ progress.percent }}% ({{ formatFileSize(progress.loaded) }} /
          {{ formatFileSize(progress.total) }})
        </p>
        <p v-if="progress.speed > 0">上传速度: {{ formatFileSize(progress.speed) }}/s</p>
      </div>
    </div>

    <!-- 上传结果 -->
    <div v-if="uploadResult" class="result-section">
      <h3>上传成功！</h3>
      <p>
        <strong>访问URL:</strong>
        <a :href="uploadResult.url" target="_blank">{{ uploadResult.url }}</a>
      </p>
      <p><strong>Location:</strong> {{ uploadResult.Location }}</p>
      <p><strong>ETag:</strong> {{ uploadResult.ETag }}</p>
      <p><strong>RequestId:</strong> {{ uploadResult.RequestId }}</p>
    </div>

    <!-- 错误信息 -->
    <div v-if="errorMessage" class="error-section">
      <h3>上传失败</h3>
      <p>{{ errorMessage }}</p>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { cosUpload, type UploadResult, type UploadProgress } from '@/cos/cosUpload'

const fileInput = ref<HTMLInputElement>()
const selectedFile = ref<File | null>(null)
const previewUrl = ref<string>('')
const uploading = ref(false)
const progress = ref<UploadProgress>({
  loaded: 0,
  total: 0,
  speed: 0,
  percent: 0,
})
const uploadResult = ref<UploadResult | null>(null)
const errorMessage = ref<string>('')

// 触发文件选择
const triggerFileSelect = () => {
  fileInput.value?.click()
}

// 处理文件选择
const handleFileSelect = (event: Event) => {
  const target = event.target as HTMLInputElement
  const file = target.files?.[0]

  if (file) {
    selectedFile.value = file

    // 创建预览URL
    if (previewUrl.value) {
      URL.revokeObjectURL(previewUrl.value)
    }
    previewUrl.value = URL.createObjectURL(file)

    // 清除之前的结果和错误
    uploadResult.value = null
    errorMessage.value = ''
  }
}

// 处理上传
const handleUpload = async () => {
  if (!selectedFile.value) {
    errorMessage.value = '请先选择要上传的图片'
    return
  }

  try {
    uploading.value = true
    errorMessage.value = ''
    uploadResult.value = null

    // 调用上传函数
    const result = await cosUpload(selectedFile.value, (progressData: UploadProgress) => {
      progress.value = progressData
    })

    uploadResult.value = result
  } catch (error) {
    errorMessage.value = error instanceof Error ? error.message : '上传失败'
  } finally {
    uploading.value = false
  }
}

// 重置函数
const handleReset = () => {
  // 清除文件选择
  selectedFile.value = null
  if (fileInput.value) {
    fileInput.value.value = ''
  }

  // 清除预览URL
  if (previewUrl.value) {
    URL.revokeObjectURL(previewUrl.value)
    previewUrl.value = ''
  }

  // 重置状态
  uploading.value = false
  progress.value = {
    loaded: 0,
    total: 0,
    speed: 0,
    percent: 0,
  }
  uploadResult.value = null
  errorMessage.value = ''
}

// 格式化文件大小
const formatFileSize = (bytes: number): string => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}
</script>

<style scoped>
.image-upload-container {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
  font-family: Arial, sans-serif;
}

.upload-section {
  margin-bottom: 20px;
  display: flex;
  gap: 10px;
  align-items: center;
}

.upload-section input[type='file'] {
  display: none;
}

.upload-section button {
  padding: 8px 16px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.upload-section button:disabled {
  background-color: #ccc;
  cursor: not-allowed;
}

.preview-section {
  margin-bottom: 20px;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 16px;
}

.preview-image {
  max-width: 100%;
  max-height: 300px;
  object-fit: contain;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.upload-controls {
  margin-bottom: 20px;
}

.button-group {
  display: flex;
  gap: 10px;
  margin-bottom: 16px;
}

.upload-controls button {
  padding: 10px 20px;
  background-color: #28a745;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
}

.upload-controls .reset-btn {
  background-color: #6c757d;
}

.upload-controls button:disabled {
  background-color: #ccc;
  cursor: not-allowed;
}

.upload-controls button:hover:not(:disabled) {
  opacity: 0.9;
}

.progress-section {
  margin-top: 16px;
}

.progress-bar {
  width: 100%;
  height: 20px;
  background-color: #f0f0f0;
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 8px;
}

.progress-fill {
  height: 100%;
  background-color: #007bff;
  transition: width 0.3s ease;
}

.result-section {
  background-color: #d4edda;
  border: 1px solid #c3e6cb;
  border-radius: 4px;
  padding: 16px;
  margin-bottom: 20px;
}

.result-section a {
  color: #007bff;
  text-decoration: none;
}

.result-section a:hover {
  text-decoration: underline;
}

.error-section {
  background-color: #f8d7da;
  border: 1px solid #f5c6cb;
  border-radius: 4px;
  padding: 16px;
  color: #721c24;
}

h2,
h3 {
  margin-top: 0;
}

p {
  margin: 8px 0;
}
</style>
